.data
	MatA: .float 4.1, 3.2, 2.3, 1.4, 5.5, 6.6, 7.7, 8.8, 2.9, 2.0, 2.1, 2.2, 5.3, 5.4, 5.5, 5.6
	MatB: .float 10.8, 11.6, 12.4, 13.2, 14.1, 15.3, 16.5, 17.7, 18.9, 19.1, 20.2, 21.3, 22.4, 23.5, 24.6, 25.7
	MatBMi: .float 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	FPU_M_Result: .float 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	MatSize: .long 4
	MatTotalLength: .long 16
info: .string "%f %f %f %f \n%f %f %f %f \n%f %f %f %f \n%f %f %f %f\n"


out: .string "%d :: %d :: %d :: %d.\n"

.text
.global main
main:

// zuerst Matrix B spiegeln um Zugriff auf die Elemente von A und B ueber
// den selben Index zu ermoeglichen

call invMatrix
// nach dem call von invMatrix wird mit MatA und mit MatBMi gearbeitet
call matrmul

movl MatTotalLength, %ecx
.outputFor:
cmpl $0, %ecx //ecx is n (counter) der schleife
je .outputEnd
	decl %ecx
        subl $8, %esp // zwar ist float nur 4 byte lang, aber mit 4 gibt es kein ergebnis
        fld FPU_M_Result(, %ecx, 4)
        fstpl (%esp)
jmp .outputFor
.outputEnd:

pushl $info
call printf
// stackpointer wieder an den richtigen platz ruecken
movl MatTotalLength, %eax // anzahl der eintraege
movl $8, %edx // wird mit der groesse pro element
mull %edx // multipliziert
addl $4, %eax // wegen der ausgabezeichenkette
addl %eax, %esp

movl $1, %eax
int $0x80




.global matrmul
matrmul:
pushl %ebp
movl %esp, %ebp

// alle positionen anlaufen
movl $0, %ecx
.matrmulFor:
cmpl MatTotalLength, %ecx //ecx is n (counter) der schleife
jge .matrmulEnd
//call debug
// aStart berechnen und auf stack legen
// aStart: n - (n mod MatSize)
movl %ecx, %eax
cltd
idivl MatSize // edx beinhaltet den rest
movl %ecx, %eax
subl %edx, %eax // eax beinhaltet jetzt aStart
pushl %eax // eax auf stack pushen
// bStart berechnen - bStart: (n mod MatSize) * MatSize
movl %edx, %eax // n mod MatSize liegt noch auf edx - keine erneute berechnung
cltd
imull MatSize
movl %eax, %edx // bStart in edx
popl %eax // aStart in eax
// start do-while schleife
/*
do {
	FPU_M_Result[n] += (MatA[aStart] * MatB[bStart]);
	aStart++;
	bStart++;
} while(aStart % MatSize != 0);
*/
.matrmulDoWhile:
fld FPU_M_Result(, %ecx, 4) // lade result zur addition
fld MatA(,%eax,4) // lade a
fmul MatBMi(,%edx,4) // lade und multipliziere b
faddp %st(0), %st(1)
fstp FPU_M_Result(, %ecx, 4)
// aStart und bStart erhoehen
incl %eax
incl %edx
// astart und bstart sichern
pushl %eax
pushl %edx
// aStart % 0 != 0
cltd
idivl MatSize
cmpl $0, %edx
// edx und eax wiederherstellen
popl %edx
popl %eax
jne .matrmulDoWhile


incl %ecx
jmp .matrmulFor
.matrmulEnd:
movl $3, %edx
movl $12, %eax
movl $6, %ecx
cltd
idivl %ecx

leave
ret




// spalten der matrix werden zu zeilen
.global invMatrix
invMatrix:
pushl %ebp
movl %esp, %ebp

movl $0, %edi // initialisierung
movl $0, %ecx

.one:
cmpl $4, %edi
jge .end
	pushl %edi // i auf stack sichern
	.two:
	cmpl MatTotalLength, %edi
	jge .endtwo
		fld MatB(, %edi, 4)
		fstp MatBMi(, %ecx, 4)
		incl %ecx
		addl $4, %edi
	jmp .two
	.endtwo:
	popl %edi // i vom stack wiederherstellen
	incl %edi // i++
jmp .one //naechster iterationsschrit


.end:
leave
ret
